import 'dart:async';
import 'dart:collection';
import 'dart:io';
import 'package:dio/dio.dart';
import 'package:flutter_design/com/qlslylq/flutterdesign/method/AppMethod.dart';
import 'package:flutter_design/com/qlslylq/flutterdesign/constant/SoftwareConstant.dart';
import 'package:flutter_design/com/qlslylq/flutterdesign/constant/UrlConstant.dart';
import 'package:flutter_design/com/qlslylq/flutterdesign/constant/KeyConstant.dart';
import 'package:flutter_design/com/qlslylq/flutterdesign/constant/HttpConstant.dart';
import 'package:flutter_design/com/qlslylq/flutterdesign/http/engine/Protocol.dart';
import 'package:flutter_design/com/qlslylq/flutterdesign/method/UserMethod.dart';
import 'package:flutter_design/com/qlslylq/flutterdesign/util/Log.dart';
import 'package:flutter_design/com/qlslylq/flutterdesign/util/TextUtils.dart';

/*
 * Http请求操作封装类 <br/>
 * 默认接入的是应用窝云后端，但接入后其已停止服务，后续待改接<br/>
 */
class HttpProtocol extends Protocol {

  static Dio http;

  Map<String, Object> params = new LinkedHashMap<String, Object>();

  HttpMethod httpMethod;

  HttpProtocol() {
    url = UrlConstant.BASE_URL;
  }

  HttpProtocol setService(String service) {
    super.setService(service);
    if (service == ("auth") || service == ("user") || service == ("file")) {
      url += ("/" + service);
    } else {
      url += ("/custom/" + service);
    }
    return this;
  }

  HttpProtocol setMethod(String method) {
    super.setMethod(method);
    url += ("/" + method);
    return this;
  }

  HttpProtocol addUrlParam(String value) {
    url += ("/" + value);
    return this;
  }

  HttpProtocol addParam(String key, Object value) {
    if (value is bool) {
      value = value as bool ? 1 : 0;
    }
    if (value != null) {
      params[key] = value;
    }
    return this;
  }

  HttpProtocol addPagerParam(int page) {
    params[HttpConstant.PARAM_PAGER_NO] = page;
    params[HttpConstant.PARAM_PAGER_SIZE] = SoftwareConstant.PAGER_SIZE;
    return this;
  }

  HttpProtocol addMaxPagerParam() {
    params[HttpConstant.PARAM_PAGER_NO] = 1;
    params[HttpConstant.PARAM_PAGER_SIZE] = SoftwareConstant.MAX_PAGER_SIZE;
    return this;
  }

  void addSignedParams() {

  }

  /*
   * GET请求<br/>
   */
  Future<Response<Map<String, dynamic>>> get() {
    httpMethod = HttpMethod.GET;
    return requestGet();
  }

  /*
   * POST请求<br/>
   */
  Future<Response<Map<String, dynamic>>> post() {
    httpMethod = HttpMethod.POST;
    return requestPost();
  }

  /*
   * 请求<br/>
   */
  Future<Response<Map<String, dynamic>>> request(HttpMethod httpMethod,
      Map<String, dynamic> requestParams) async {
    Dio http = createDefaultHttpClient();
    try {
      Response<Map<String, dynamic>> response;
      if (httpMethod == HttpMethod.GET) {
        response = await http.get(url, queryParameters: requestParams);
      } else if (httpMethod == HttpMethod.POST) {
        response = await http.post(url, queryParameters: requestParams);
      }
      return response;
    } catch (e) {
      outputException(e);
    }
    return null;
  }

  Future<Response<Map<String, dynamic>>> requestGet() async {
    Dio http = createDefaultHttpClient();
    try {
      Log.e("http", 'url：$url');
      Response<Map<String, dynamic>> response = await http.get(
          url, queryParameters: prepareRequestParams());
      int statusCode = response.statusCode;
      Log.d("http", 'requestParams：${response.request.headers}');
      Log.e("http", "status:${statusCode.toString()}");
      Log.e("http", response.data);
      return response;
    } catch (e) {
      outputException(e);
    }
    return null;
  }

  Future<Response<Map<String, dynamic>>> requestPost() async {
    Dio http = createDefaultHttpClient();
    try {
      Log.ln();
      Log.e("http", 'url：$url');
      Response<Map<String, dynamic>> response = await http.post(
          url, queryParameters: prepareRequestParams());
      int statusCode = response.statusCode;
      Log.d("http", 'requestParams：${response.request.queryParameters}');
      Log.e("http", "status:${statusCode.toString()}");
      Log.e("http", response.data);
      Log.ln();
      return response;
    } catch (e) {
      outputException(e);
    }
    return null;
  }

  Map<String, dynamic> prepareRequestParams() {
    addSignedParams();
    Map<String, dynamic> requestParams = addParams();
    addHeader();
    return requestParams;
  }

  Map<String, dynamic> addParams() {
    if (httpMethod == HttpMethod.GET) {
      return params;
    } else if (httpMethod == HttpMethod.POST) {
      Map<String, dynamic>headers = http.options.headers;
      if (params.containsKey(HttpConstant.PARAM_PAGER_NO)) {
        headers[HttpConstant.PARAM_PAGER_NO] =
        params[HttpConstant.PARAM_PAGER_NO];
      }
      if (params.containsKey(HttpConstant.PARAM_PAGER_SIZE)) {
        headers[HttpConstant.PARAM_PAGER_SIZE] =
        params[HttpConstant.PARAM_PAGER_SIZE];
      }
      return params;
    }
    return params;
  }

  void addHeader() {
    Map<String, dynamic>headers = http.options.headers;

    headers[HttpConstant.PARAM_APP_KEY] = KeyConstant.APP_KEY_ADMX;
    String token = HttpConstant.TOKEN;
    if (TextUtils.isEmpty(token)) {
      token = UserMethod.getTokenFromProperty();
      HttpConstant.TOKEN = token;
    }
    if (!TextUtils.isEmpty(token)) {
      headers[HttpConstant.PARAM_TOKEN] = token;
    }
  }

  Dio createDefaultHttpClient() {
    if (http == null) {
      http = new Dio(new BaseOptions(
        baseUrl: UrlConstant.BASE_URL,
        connectTimeout: 5000,
        receiveTimeout: 30000,
        headers: {
          HttpConstant.PARAM_APP_KEY: KeyConstant.APP_KEY_ADMX,
          HttpHeaders.userAgentHeader: AppMethod.getUserAgent(),
          "api": "1.0",
        },
        contentType: ContentType.json,
        responseType: ResponseType.json,
      ));
    }
    if (service == "file") {
      http.options.receiveTimeout = 15 * 12 * 1000;
    } else {
      http.options.receiveTimeout = 20 * 1000;
    }
    return http;
  }

/*
   * 输出网络错误详情<br/>
   */
  void outputException(e) {
    Log.e("http", e);
  }

/*
   * 获取基本url与参数的拼接字符串<br/>
   * 只能在网络请求返回之后调用，才能获取准确的参数<br/>
   */
  String getUrl() {
    if (params.length == 0) {
      return url;
    } else {
      StringBuffer sb = new StringBuffer(url + "?");
      params.forEach((key, value) =>
      {
      sb..write(key + "=" + value + "&")
      });
      sb
        ..write(
            HttpConstant.PARAM_APP_KEY + "=" + KeyConstant.APP_KEY_ADMX + "&");
      sb..write(HttpConstant.PARAM_TOKEN + "=" + HttpConstant.TOKEN);
      return sb.toString();
    }
  }

/*
   * 获取参数<br/>
   * 只能在网络请求返回之后调用，才能获取准确的参数<br/>
   */
  Object getParams() {
    return params;
  }

/*
   * 清除静态数据<br/>
   */
  static void clearStaticData
      () {

  }

}
